home *** CD-ROM | disk | FTP | other *** search
/ 17 Bit Software 6: Level 6 / 17 Bit - Level 6 (1998)(Epic Marketing)[!].iso / quartz / q0429.dms / q0429.adf / libshade / picture.c < prev    next >
C/C++ Source or Header  |  1992-05-20  |  8KB  |  338 lines

  1. /*
  2.  * picture.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb, Rod G. Bogart
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * $Id: picture.c,v 4.0.1.2 92/02/07 09:22:20 cek Exp Locker: cek $
  17.  *
  18.  * $Log:    picture.c,v $
  19.  * Revision 4.0.1.2  92/02/07  09:22:20  cek
  20.  * patch6: Fixed typo in MTV error message.
  21.  * 
  22.  * Revision 4.0.1.1  92/01/10  16:28:28  cek
  23.  * patch3: Added check for nonexistent patial image file.
  24.  * patch3: Fixed declaration of nrow in count_rle_rows().
  25.  * patch3: Changed level of several error messages.
  26.  * 
  27.  * Revision 4.0  91/07/17  14:47:00  kolb
  28.  * Initial version.
  29.  * 
  30.  */
  31. #include "rayshade.h"
  32. #include "picture.h"
  33. #include "viewing.h"
  34. #include "options.h"
  35. #include "stats.h"
  36.  
  37. #ifdef URT
  38. unsigned char **outptr;        /* Output buffer */
  39. static int count_rle_rows();
  40. #endif
  41.  
  42. /*
  43.  * Convert floating-point (0.-1.) to unsigned char (0-255), with no gamma
  44.  * correction.
  45.  */
  46. unsigned char
  47. correct(x)
  48. Float x;
  49. {
  50.     /*
  51.      * Truncate values < 0 or > 1.
  52.      */
  53.     if (x < 0)
  54.         return 0;
  55.     if (x > 1.)
  56.         return 255;
  57.     return (unsigned char)(x * 255.);
  58. }
  59.  
  60. #ifdef URT
  61. /*
  62.  * Open image file and write RLE header.
  63.  */
  64. void
  65. PictureStart(argv)
  66. char **argv;
  67. {
  68.     char gammacom[40];
  69.  
  70.     if (Options.framenum != Options.startframe) {
  71.         /*
  72.          * We've been here before;
  73.          * write a new header and return.
  74.          */
  75.         rle_put_setup(&rle_dflt_hdr);
  76.         return;
  77.     }
  78.     /*
  79.      * If Appending, then we know that outfile is valid, 'cause
  80.      * we've already read its header.
  81.      */
  82.     if (Options.appending) {
  83.         Options.pictfile = fopen(Options.imgname, "a");
  84.         if (Options.pictfile == (FILE *)0)
  85.             RLerror(RL_PANIC, "Cannot append to %s?!\n",
  86.                     Options.imgname);
  87.         rle_dflt_hdr.rle_file = Options.pictfile;
  88.         rle_put_init(&rle_dflt_hdr);
  89.     } else {
  90.         /*
  91.          * Starting image from scatch.
  92.          */
  93.         if (Options.imgname) {
  94.             Options.pictfile = fopen(Options.imgname, "w");
  95.             if (Options.pictfile == (FILE *)NULL)
  96.                 RLerror(RL_ABORT,"Cannot open %s for writing.",
  97.                     Options.imgname);
  98.         } else
  99.             Options.pictfile = stdout;
  100.  
  101.         rle_dflt_hdr.xmax = Screen.maxx;
  102.         rle_dflt_hdr.ymax = Screen.maxy;
  103.         rle_dflt_hdr.xmin = Screen.minx;
  104.         rle_dflt_hdr.ymin = Screen.miny;
  105.         rle_dflt_hdr.alpha = Options.alpha;
  106.         if (Options.alpha)
  107.             RLE_SET_BIT(rle_dflt_hdr, RLE_ALPHA);
  108.         if (Options.exp_output) {
  109.             RLE_SET_BIT(rle_dflt_hdr, RLE_BLUE + 1);
  110.             rle_dflt_hdr.ncolors = 4;
  111.             rle_putcom("exponential_data", &rle_dflt_hdr);
  112.         }
  113.         else
  114.             rle_dflt_hdr.ncolors = 3;
  115.         /*
  116.           * Document image gamma in RLE comment area.
  117.          * Options.gamma has been inverted.
  118.           */
  119.         (void)sprintf(gammacom, "display_gamma=%g", 1./Options.gamma);
  120.         rle_putcom(gammacom, &rle_dflt_hdr);
  121.         /*
  122.           * Document command line in RLE history.
  123.           */
  124.         rle_addhist(argv, (rle_hdr *)0, &rle_dflt_hdr);
  125.         rle_dflt_hdr.rle_file = Options.pictfile;
  126.         rle_put_setup(&rle_dflt_hdr);
  127.         /*
  128.           * Flush the header.  If we don't, and LINDA forks off
  129.           * a bunch of workers, strange things will happen (they'll
  130.           * all flush the buffer when they die, and you end up with
  131.           * lots of headers at the end of the file).
  132.           */
  133.         (void)fflush(rle_dflt_hdr.rle_file);
  134.     }
  135.  
  136.     if (rle_row_alloc(&rle_dflt_hdr, &outptr) < 0)
  137.         RLerror(RL_PANIC, "Unable to allocate image memory.\n");
  138. }
  139.  
  140. /*
  141.  * Read RLE header to which we are appending in order determine
  142.  * old resolution, window location, and the like.
  143.  */
  144. void
  145. PictureSetWindow()
  146. {
  147.     if (Options.imgname == (char *)NULL)
  148.         RLerror(RL_ABORT,
  149.             "No partially-completed image file specified.\n");
  150.  
  151.     /*
  152.      * Open image and read RLE header.
  153.      */
  154.     Options.pictfile = fopen(Options.imgname, "r");
  155.     if (Options.pictfile == (FILE *)NULL) {
  156.         RLerror(RL_ABORT, "Cannot open image file %s.\n",
  157.                     Options.imgname);
  158.     }
  159.     rle_dflt_hdr.rle_file = Options.pictfile;
  160.     rle_get_setup_ok(&rle_dflt_hdr, "rayshade", Options.imgname);
  161.  
  162.     /*
  163.      * If user specified a window that does not match what's in
  164.      * the header, complain.
  165.     if (Screen.minx != UNSET && Screen.minx != rle_dflt_hdr.xmin ||
  166.         Screen.miny != UNSET && Screen.miny != rle_dflt_hdr.ymin ||
  167.         Screen.maxx != UNSET && Screen.maxx != rle_dflt_hdr.xmax ||
  168.         Screen.maxy != UNSET && Screen.maxy != rle_dflt_hdr.ymax)
  169.         RLerror(RL_ADVISE, "Image window: %d - %d, %d - %d.\n",
  170.             rle_dflt_hdr.xmin, rle_dflt_hdr.xmax,
  171.             rle_dflt_hdr.ymin, rle_dflt_hdr.ymax);
  172.      */
  173.     /*
  174.      * Set window.
  175.      */
  176.     Screen.minx = rle_dflt_hdr.xmin;
  177.     Screen.miny = rle_dflt_hdr.ymin;
  178.     Screen.maxx = rle_dflt_hdr.xmax;
  179.     Screen.maxy = rle_dflt_hdr.ymax;
  180.  
  181.     /*
  182.      * Set alpha.  Warn the user if the alpha option doesn't reflect
  183.      * what's already been rendered.
  184.      */
  185.     if (Options.alpha != rle_dflt_hdr.alpha)
  186.         RLerror(RL_WARN, "Image %s %s an alpha channel.\n",
  187.             Options.imgname,
  188.             rle_dflt_hdr.alpha ? "has" : "does not have");
  189.  
  190.     Options.alpha = rle_dflt_hdr.alpha;
  191.  
  192.     /*
  193.      * Determine number of scanlines written to file.
  194.      */
  195.     Screen.miny += count_rle_rows(&rle_dflt_hdr);
  196.     if (Screen.miny >= Screen.maxy) {
  197.         fprintf(stderr, "\"%s\" is a complete image.\n",
  198.             Options.imgname);
  199.         exit(0);
  200.     }
  201.     fprintf(Stats.fstats,"Continuing \"%s\" at scanline #%d.\n",
  202.         Options.imgname, Screen.miny);
  203.     (void)fclose(Options.pictfile);
  204. }
  205.  
  206. static int
  207. count_rle_rows( hdr )
  208. rle_hdr *hdr;
  209. {
  210.     rle_op **raw;
  211.     int *nraw, y, ynext;
  212.  
  213.     if (rle_raw_alloc( hdr, &raw, &nraw ) < 0)  {
  214.         RLerror(RL_PANIC,
  215.             "Unable to allocate memory in count_rle_rows.\n");
  216.     }
  217.  
  218.     y = hdr->ymin;
  219.     while ((ynext = rle_getraw( hdr, raw, nraw )) != 32768) {
  220.         y = ynext+1;
  221.         rle_freeraw( hdr, raw, nraw );
  222.     }
  223.  
  224.     /* Free memory. */
  225.     rle_raw_free( hdr, raw, nraw );
  226.  
  227.     return y - hdr->ymin;
  228. }
  229.  
  230. /*
  231.  * Write a scanline of output.
  232.  * "buf" is an array of Color structures of size Screen.xsize.  Each color
  233.  * component is normalized to [0, 1.].
  234.  */
  235. void
  236. PictureWriteLine(buf)
  237. Pixel *buf;
  238. {
  239.     register int i, chan;
  240.     float floats[3];
  241.     rle_pixel pixels[4];
  242.  
  243.     for(i = 0; i < Screen.xsize; i++) {
  244.         if (!Options.exp_output) {
  245.             /*
  246.              * Scale colors to fit unsigned char and check for
  247.              * over/underflow.
  248.              */
  249.             outptr[0][i] = CORRECT(buf[i].r);
  250.             outptr[1][i] = CORRECT(buf[i].g);
  251.             outptr[2][i] = CORRECT(buf[i].b);
  252.         } else {
  253.             /*
  254.              * Convert 3 floats to 4 unsigned chars for
  255.              * 'exponential_data' RLE file.
  256.              */
  257.             floats[0] = GAMMACORRECT(buf[i].r);
  258.             floats[1] = GAMMACORRECT(buf[i].g);
  259.             floats[2] = GAMMACORRECT(buf[i].b);
  260.             float_to_exp( 3, floats, pixels );
  261.             for (chan = 0; chan <= 3; chan++)
  262.                 outptr[chan][i] = pixels[chan];
  263.         }
  264.         if (Options.alpha)
  265.             /*
  266.              * Don't gamma correct alpha channel.
  267.              */
  268.             outptr[-1][i] = correct(buf[i].alpha);
  269.     }
  270.     rle_putrow(outptr, Screen.xsize, &rle_dflt_hdr);
  271. }
  272.  
  273. /*
  274.  * End the frame.
  275.  */
  276. void
  277. PictureFrameEnd()
  278. {
  279.     rle_puteof(&rle_dflt_hdr);
  280. }
  281.  
  282. /*
  283.  * Close image file.
  284.  */
  285. void
  286. PictureEnd()
  287. {
  288.     (void)fclose(Options.pictfile);
  289. }
  290.  
  291. #else /* !URT */
  292. void
  293. PictureStart(argv)
  294. char **argv;
  295. {
  296.     if (Options.imgname) {
  297.         Options.pictfile = fopen(Options.imgname, "w");
  298.         if (Options.pictfile == (FILE *)NULL)
  299.             RLerror(RL_ABORT, "Cannot open %s for writing.",
  300.                 Options.imgname);
  301.     } else
  302.         Options.pictfile = stdout;
  303.  
  304.     fprintf(Options.pictfile,"%d %d\n",Screen.xsize, Screen.ysize);
  305.  
  306.     (void)fflush(Options.pictfile);
  307. }
  308.  
  309. void
  310. PictureWriteLine(buf)
  311. Pixel *buf;
  312. {
  313.     register int i;
  314.  
  315.     for (i = 0; i < Screen.xsize; i++) {
  316.         (void)fputc((int)CORRECT(buf[i].r), Options.pictfile);
  317.         (void)fputc((int)CORRECT(buf[i].g), Options.pictfile);
  318.         (void)fputc((int)CORRECT(buf[i].b), Options.pictfile);
  319.     }
  320.     (void)fflush(Options.pictfile);
  321. }
  322.  
  323. void
  324. PictureFrameEnd()
  325. {
  326.     /*
  327.      * Don't do anything -- generic format has no end-of-image marker.
  328.      */
  329. }
  330.  
  331. void
  332. PictureEnd()
  333. {
  334.     (void)fclose(Options.pictfile);
  335. }
  336.  
  337. #endif /* URT */
  338.